package lxn;

import static robocode.util.Utils.normalRelativeAngleDegrees;
import java.awt.Color;
import robocode.Robot;
import robocode.HitByBulletEvent;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.ScannedRobotEvent;

/**
 * Leonardo Nguyen's competitively designed robot.
 *
 * @author Leonardo Nguyen
 * @version Java 1.6.0_21
 */
public class Obon extends Robot { 
  
  private String trackedRobot = null;
  // Default starting health for robots is 100.
  private double trackedRobotEnergy = 100;
    
  // The rate of turning the gun in pixels.
  private double rotationRate = 10;
  // The amount of rounds the radar has failed in detecting the tracked robot.
  private int roundOfUndetection = 0;
  
  /**
   * Main function, which gives the robot action(s).
   */
  public void run() {
    
    setBodyColor(Color.DARK_GRAY);
    setGunColor(Color.BLACK);
    setRadarColor(Color.WHITE);
    setBulletColor(Color.RED);
    setScanColor(Color.ORANGE);
    
    setAdjustGunForRobotTurn(true);
    
    while (true) {
      
      // Turn the Gun (looks for enemy)
      turnGunRight(rotationRate);
      
      // Keep track of how long we've been looking
      roundOfUndetection++;
      
      // If we've haven't seen our target for 2 turns, look left
      if (roundOfUndetection > 2) {
        rotationRate = -10;
      }
      
      // If we still haven't seen our target for 5 turns, look right
      if (roundOfUndetection > 5) {
        rotationRate = 10;
      }
      
      // Lost track of target, look for a new target robot instead.
      if (roundOfUndetection > 15 && trackedRobot != null) {
        trackedRobot = null;
      }
    }
  }
  
  /**
   * Upon detecting an enemy robot, track it, turn both this robot's heading and gun to face.
   * the tracked robot.
   * @param e Event that occurs when Obon detects an enemy robot.
   */
  public void onScannedRobot(ScannedRobotEvent e) {
    
    // If we have a target, and this isn't it, return immediately
    // so we can get more ScannedRobotEvents.
    // Code taken from Tracker robot sample.
    if (trackedRobot != null && !e.getName().equals(trackedRobot)) {
      return;
    }
    
    // Found a robot to track.
    // Code taken from Tracker robot sample.
    if (trackedRobot == null) {
      trackedRobot = e.getName();
      trackedRobotEnergy = e.getEnergy();
    }
    
    // Reset the counter of how long this robot hasn't been able to detect its target.
    roundOfUndetection = 0;
    
    // Target the tracked robot.
    rotationRate = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading()));
    turnGunRight(rotationRate); 
    
    // Fire and don't move closer to target.
    if (e.getDistance() <= 400) {
      fire(600 / e.getDistance());
    }
    else {
      // Turn this robot's heading a little off-side of the detected target so we can 
      // flank the target robot after a movement later.
      turnRight(e.getBearing() + 15);
      fire(600 / e.getDistance());
      
      // If detected target is quite far, move in, but only half the distance from the target to
      // limit time used for movement.
      if (e.getDistance() > 400 && e.getDistance() <= 600) {
        ahead(e.getDistance() / 2);
      }
    }
    
    // Keep moving while a target is detected to remain mobile.
    ahead(50);
  }
  
  /**
   * Upon being hit by a bullet, this robot will stand firm and refuse to dodge if it's current
   * tracked target's energy is low so it can focus on eliminating it or otherwise face 45 degrees
   * bearing from where the bullet struck this robot and back up 100 pixels to avoid further fire.
   * @param e Event that occurs when Obon is struck by a bullet. 
   */
  public void onHitByBullet(HitByBulletEvent e) {
    
    // Don't dodge if our current target has low energy and this robot's gun isn't overheated.
    // Stand firm and go for the kill.
    if (trackedRobotEnergy <= 35 && getGunHeat() == 0) {
      return;
    }
    
    // If this robot's energy is high, than remain confident and don't dodge.
    if (getEnergy() > 90  && getGunHeat() == 0) {
      return;
    }
    
    // There may be a more immediate threat than the current tracked target if this robot is
    // getting struck by bullets, so abandon current target.
    trackedRobot = null;
    
    // If anywhere near 75 pixels of a wall, get away by either moving 75 pixels away or into
    // the wall and initiate onHitWall method, which will turn this robot to face away from 
    // the wall.
    if (getX() < 75 || getX() > (getBattleFieldWidth() - 75) 
        || getY() < 75 || getY() > (getBattleFieldHeight() - 75)) {
      ahead(75);
      return;
    }
    
    // Back up to avoid further fire.
    turnRight(e.getBearing() + 45);
    back(100);

    scan();
  }
  
  /**
   * Upon hitting a wall, turn this robot around to face away from the wall.
   * @param e Event that occurs when Obon collides into a wall.
   */
  public void onHitWall(HitWallEvent e) {

    turnRight(e.getBearing() - 225);
  }
  
  /**
   * Upon colliding with a robot, if current tracked robot's energy is greater than 49 points,
   * make the robot that collided with this robot the new tracked target since it is closer
   * and an immediate threat.
   * @param e Event that occurs when Obon collides with another robot.
   */
  public void onHitRobot(HitRobotEvent e) {
    
    if (trackedRobotEnergy >= 50) {
      trackedRobot = e.getName();
    }
  }
}